/**
 @file ctc_asw_linkagg.c

 @date 2020-06-12

 @version v1.0

---file comments----
*/

#include "ctc_asw_common.h"
#include "ctc_asw_linkagg.h"
#include "asw/include/drv_api.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/

#define CTC_ASW_MAX_LINKAGG_ID 4

enum _ctc_linkagg_psc_key_e
{
    _CTC_LINKAGG_PSC_KEY_MACSA         = 0,
    _CTC_LINKAGG_PSC_KEY_MACDA         = 1,
    _CTC_LINKAGG_PSC_KEY_SIP           = 2,
    _CTC_LINKAGG_PSC_KEY_DIP           = 3,
    _CTC_LINKAGG_PSC_KEY_LAG_PKT_CNT   = 4,
    _CTC_LINKAGG_PSC_KEY_ETH_TYPE      = 5,
    _CTC_LINKAGG_PSC_KEY_SRC_PORT      = 6,
    _CTC_LINKAGG_PSC_KEY_IP_PROTOCOL   = 7,
    _CTC_LINKAGG_PSC_KEY_L4_DEST_PORT  = 8,
    _CTC_LINKAGG_PSC_KEY_L4_SRC_PORT   = 9
};
typedef enum _ctc_linkagg_psc_key_e _ctc_linkagg_psc_key_t;
/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
int32
ctc_asw_linkagg_add_port(uint8 lchip,  uint16 tid,  uint32 gport)
{
    IngressPort_m ingress_port;
    uint32 cmd = 0;
    int32  ret = 0;

    CTC_MAX_VALUE_CHECK(tid, CTC_ASW_MAX_LINKAGG_ID);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip,gport,cmd,&ingress_port);
    SetIngressPort(V,trunkId_f,&ingress_port,tid);
    SetIngressPort(V,trunkVld_f,&ingress_port,1);
    cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip,gport,cmd,&ingress_port));
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_linkagg_remove_port(uint8 lchip,  uint16 tid,  uint32 gport)
{
    IngressPort_m ingress_port;
    uint32 tid_hw = 0;
    uint32 member_enable = 0;
    uint32 cmd = 0;
    int32  ret = 0;

    CTC_MAX_VALUE_CHECK(tid, CTC_ASW_MAX_LINKAGG_ID);
    CTC_MAX_GPORT_CHECK(gport);

    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip,gport,cmd,&ingress_port);
    tid_hw = GetIngressPort(V,trunkId_f,&ingress_port);
    member_enable = GetIngressPort(V,trunkVld_f,&ingress_port);
    if ((tid_hw != tid) || (member_enable == 0))
    {
        CTC_API_UNLOCK(lchip);
        return CTC_E_INVALID_PARAM;
    }
    SetIngressPort(V,trunkId_f,&ingress_port,0);
    SetIngressPort(V,trunkVld_f,&ingress_port,0);
    cmd = DRV_IOW(IngressPort_t, DRV_ENTRY_FLAG);
    ret = ret ? ret : (DRV_IOCTL(lchip,gport,cmd,&ingress_port));
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_linkagg_get_member_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* cnt)
{
    IngressPort_m ingress_port;
    uint32 tid_hw = 0;
    uint32 member_enable = 0;
    uint32 cmd = 0;
    int32  ret = 0;
    uint8 index = 0;

    CTC_MAX_VALUE_CHECK(tid, CTC_ASW_MAX_LINKAGG_ID);
    CTC_PTR_VALID_CHECK(p_gports);
    CTC_PTR_VALID_CHECK(cnt);

    *cnt = 0;
    CTC_API_LOCK(lchip);
    for(index=0; index<=CTC_ASW_MAX_PHY_PORT; index++)
    {
        cmd = DRV_IOR(IngressPort_t, DRV_ENTRY_FLAG);
        ret = DRV_IOCTL(lchip,index,cmd,&ingress_port);
        tid_hw = GetIngressPort(V,trunkId_f,&ingress_port);
        member_enable = GetIngressPort(V,trunkVld_f,&ingress_port);
        if ((tid_hw != tid) || (member_enable == 0))
        {
           continue;
        }
        p_gports[(*cnt)++] = index;
    }
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_linkagg_set_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc)
{
    uint32 key_sel = 0;
    LagHashControl_m lag_hash;
    uint32 cmd = 0;
    int32  ret = 0;
    uint8  loop = 0;
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(LagHashControl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &lag_hash);
    key_sel = GetLagHashControl(V, keySel_f, &lag_hash);
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2))
    {
        if (CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACSA))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_MACSA);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_MACSA);
        }
        if (CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACDA))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_MACDA);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_MACDA);
        }
        if (CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_PORT))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_SRC_PORT);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_SRC_PORT);
        }
        if (CTC_FLAG_ISSET(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_ETHERTYPE))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_ETH_TYPE);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_ETH_TYPE);
        }
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_IP))
    {
        if (CTC_FLAG_ISSET(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_PROTOCOL))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_IP_PROTOCOL);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_IP_PROTOCOL);
        }
        if (CTC_FLAG_ISSET(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPSA))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_SIP);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_SIP);
        }
        if (CTC_FLAG_ISSET(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPDA))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_DIP);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_DIP);
        }
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L4))
    {
        if (CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_SRC_PORT))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_SRC_PORT);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_SRC_PORT);
        }
        if (CTC_FLAG_ISSET(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_DST_PORT))
        {
            CTC_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_DEST_PORT);
        }
        else
        {
            CTC_BIT_UNSET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_DEST_PORT);
        }
    }
    SetLagHashControl(V, keySel_f, &lag_hash, key_sel);
    cmd = DRV_IOW(LagHashControl_t, DRV_ENTRY_FLAG);
    for (loop= 0; loop <= CTC_ASW_MAX_LINKAGG_ID ; loop++)
    {
        ret = ret ? ret : (DRV_IOCTL(lchip, loop, cmd, &lag_hash));
    }
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_linkagg_get_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc)
{
    uint32 key_sel = 0;
    LagHashControl_m lag_hash;
    uint32 cmd = 0;
    int32  ret = 0;
    CTC_API_LOCK(lchip);
    cmd = DRV_IOR(LagHashControl_t, DRV_ENTRY_FLAG);
    ret = DRV_IOCTL(lchip, 0, cmd, &lag_hash);
    key_sel = GetLagHashControl(V, keySel_f, &lag_hash);
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L2))
    {
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_MACSA))
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACSA);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACSA);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_MACDA))
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACDA);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_MACDA);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_SRC_PORT))
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_PORT);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_PORT);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_ETH_TYPE))
        {
            CTC_SET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_ETHERTYPE);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l2_flag, CTC_LINKAGG_PSC_L2_ETHERTYPE);
        }
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_IP))
    {
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_IP_PROTOCOL))
        {
            CTC_SET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_PROTOCOL);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_PROTOCOL);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_SIP))
        {
            CTC_SET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPSA);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPSA);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_DIP))
        {
            CTC_SET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPDA);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->ip_flag, CTC_LINKAGG_PSC_IP_IPDA);
        }
    }
    if (CTC_FLAG_ISSET(p_psc->psc_type_bitmap, CTC_LINKAGG_PSC_TYPE_L4))
    {
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_SRC_PORT))
        {
            CTC_SET_FLAG(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_SRC_PORT);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_SRC_PORT);
        }
        if (CTC_IS_BIT_SET(key_sel, _CTC_LINKAGG_PSC_KEY_L4_DEST_PORT))
        {
            CTC_SET_FLAG(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_DST_PORT);
        }
        else
        {
            CTC_UNSET_FLAG(p_psc->l4_flag, CTC_LINKAGG_PSC_L4_DST_PORT);
        }
    }
    CTC_API_UNLOCK(lchip);
    return ret;
}

int32
ctc_asw_linkagg_init(uint8 lchip, void* linkagg_global_cfg)
{
    return CTC_E_NONE;
}

int32
ctc_asw_linkagg_deinit(uint8 lchip)
{
    return CTC_E_NONE;
}
